#include <common.h>
#include <privsock.h>

//初始化内部进程间通信通道
void priv_sock_init(session_t *sess)
{
	//这里两个父子进程之间采用sockpair方式进行通信
	int sockfds[2];
	if(socketpair(AF_UNIX,SOCK_STREAM,
			0,sockfds) < 0) {
		ERR_EXIT("socketpair");
	}
	sess->parent_fd = sockfds[0];
	sess->child_fd = sockfds[1];
}
//关闭内部进程间通信通道
void priv_sock_close(session_t *sess)
{
	if(sess->child_fd != -1) {
		close(sess->child_fd);
		sess->child_fd = -1;
	}
	if(sess->parent_fd != -1) {
		close(sess->parent_fd);
		sess->parent_fd = -1;
	}
}
//设置父进程环境
void priv_sock_set_parent_context(session_t *sess)
{
	if(sess->child_fd != -1) {
		close(sess->child_fd);
		sess->child_fd = -1;
	}
}
//设置子进程环境
void priv_sock_set_child_context(session_t *sess)
{
	if(sess->parent_fd != -1) {
		close(sess->parent_fd);
		sess->parent_fd = -1;
	}
}

void priv_sock_send_cmd(int fd, char cmd)
{
	int ret;
	ret = writen(fd,&cmd,sizeof(cmd));
	if(ret != sizeof(cmd)) {
		fprintf(stderr,"%s error\n",__func__);
		exit(EXIT_FAILURE);
	}
}
char priv_sock_get_cmd(int fd)
{
	int ret;
	char cmd;
	do {
		ret = readn(fd,&cmd,sizeof(cmd));
	} while(ret < 0 && errno == ETIMEDOUT);
	if(0 == ret) {
		DEBUG_PRINT("connect close.\n");
		exit(EXIT_SUCCESS);
	}
	if(ret != sizeof(cmd)) {
		fprintf(stderr,"%s error\n",__func__);
		exit(EXIT_FAILURE);
	}
	return cmd;
}
void priv_sock_send_result(int fd, char res)
{
	int ret;
	ret = writen(fd,&res,sizeof(res));
	if(ret != sizeof(res)) {
		fprintf(stderr,"%s error\n",__func__);
		exit(EXIT_FAILURE);
	}
}
char priv_sock_get_result(int fd)
{
	int ret;
	char res;
	do {
		ret = readn(fd,&res,sizeof(res));
	} while(ret < 0 && errno == ETIMEDOUT);
	if(ret != sizeof(res)) {
		fprintf(stderr,"%s error\n",__func__);
		exit(EXIT_FAILURE);
	}
	return res;
}

void priv_sock_send_int(int fd, int the_int)
{
	int ret;
	ret = writen(fd,&the_int,sizeof(the_int));
	if(ret != sizeof(the_int)) {
		fprintf(stderr,"%s error\n",__func__);
		exit(EXIT_FAILURE);
	}
}
int priv_sock_get_int(int fd)
{
	int ret;
	int res;
	do {
		ret = readn(fd,&res,sizeof(res));
	} while(ret < 0 && errno == ETIMEDOUT);
	
	if(ret != sizeof(res)) {
		fprintf(stderr,"%s error\n",__func__);
		exit(EXIT_FAILURE);
	}
	return res;
}
void priv_sock_send_buf(int fd, const char *buf, unsigned int len)
{
	priv_sock_send_int(fd,(int)len);
	int ret;
	ret = writen(fd,buf,len);
	if(ret != len) {
		fprintf(stderr,"%s error\n",__func__);
		exit(EXIT_FAILURE);
	}
}
void priv_sock_recv_buf(int fd, char *buf, unsigned int len)
{
	uint32_t recv_len = (uint32_t)priv_sock_get_int(fd);
	if(recv_len > len) {
		fprintf(stderr,"%s buf len is not enough.\n",__func__);
		exit(EXIT_FAILURE);
	}
	int ret;
	do {
		ret = readn(fd,buf,recv_len);
	} while(ret < 0 && errno == ETIMEDOUT);
	if(ret != (int)recv_len) {
		fprintf(stderr,"%s error\n",__func__);
		exit(EXIT_FAILURE);
	}
}
void priv_sock_send_fd(int sock_fd, int fd)
{
	int ret;
	ret = send_fd(sock_fd,fd);
	if(ret < 0) {
		fprintf(stderr,"%s error\n",__func__);
		exit(EXIT_FAILURE);
	}
}
int priv_sock_recv_fd(int sock_fd)
{
	int ret;
	ret = recv_fd(sock_fd);
	if(ret < 0) {
		fprintf(stderr,"%s error\n",__func__);
		perror("recv_fd");
		exit(EXIT_FAILURE);
	}
	return ret;
}
